#pragma once 

#include <iostream>
#include <string>
#include <queue>
#include <pthread.h>
#include "mutex.hpp"
#include "Conddex.hpp"

using namespace MutexModule;
using namespace ConddexModule;

const int defaultcap = 5;
template <typename T>
class blockqueue
{
    private:
    bool isfull()
    {
        return _q.size()>=_cap;
    }
    bool isempty()
    {
        return _q.empty();
    }
    public:
    blockqueue(int cap=defaultcap)
    :_cap(cap),_c_slepp_num(0),_p_sleep_num(0)
    {
    }
    void equeue(const T &in)
    {
        lockguard guard(_mutex);
        //生产者调用
        while(isfull())
        {
             _p_sleep_num++;
             //问题一：休眠失败
             //问题二：条件并不满足，伪唤醒
            _full_cond.wait(_mutex);//调用成功，挂起当前线程之前，释放当前锁
            //重新需要当前线程，需要重新申请锁
            _p_sleep_num--;
        }
        //走到这里确保是有空间的
        _q.push(in);
        //临时方案
        if(_c_slepp_num>0)
        {
        //     pthread_cond_signal(&_empty_cond);  
        // pthread_cond_signal(&_empty_cond);  //放在前后都可以
        // pthread_mutex_unlock(&_mutex);
        _empty_cond.signal();
        std::cout<<"唤醒了消费者"<<std::endl;
        }
    }
    T   pop()
    {
        //消费者调用
        lockguard guard(_mutex);
        while(isempty())
        {
            _c_slepp_num++;
           _empty_cond.wait(_mutex);
            _c_slepp_num--;
        }
        T data =_q.front();
        _q.pop();
        
        if(_p_sleep_num>0)
        {
        //     pthread_cond_signal(&_empty_cond);  
        // pthread_cond_signal(&_empty_cond);  //放在前后都可以
        // pthread_mutex_unlock(&_mutex);
        _full_cond.signal();
        std::cout<<"唤醒了生产者"<<std::endl;
        }
        return data;
    }
    ~blockqueue()
    {
    }
    private:
    std::queue<T> _q;//队列本身，临界资源
    int _cap;//容量大小

    Mutex _mutex;
    Conddex _full_cond;//空间满时条件变量
    Conddex _empty_cond;//空间空时条件变量
    int _c_slepp_num;
    int _p_sleep_num;

};